﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Windows.Forms;
using System.Drawing;

namespace ALDIOrganizer
{
    public partial class Cell
    {
        [NonSerialized]
        private CachedStyle _CellStyle;
        public CachedStyle CellStyle
        {
            get
            {
                return _CellStyle;
            }
            set
            {
                _CellStyle = value;
                GetParent.TriggerOnCellStyleChangedEvent(this);
            }
        }

        private CachedStyle ComputeStyle()
        {
            var style = new CachedStyle();
            var assigned = new List<Style>();

            var which = 0;
            var isNativeElement = false;

            #region Step #1 - applying basic colour, depending On the CellType of the Cell
            switch (MyCellType)
            {
                case CellType.Blank:
                    {
                        which = HasAnyNotes? Theme.AnyNotes : Theme.Blank;                        
                        break;
                    }
                case CellType.Dead:
                    {
                        which = Theme.NotEmployed;
                        break;
                    }
                case CellType.Employee:
                    {
                        which = Theme.Employee;
                        isNativeElement = true;
                        break;
                    }
                case CellType.TotalHours:
                    {
                        which = Theme.TotalHours;
                        isNativeElement = true;
                        break;

                    }
                case CellType.Holiday:
                    {
                        which = Theme.Holidays;
                        break;
                    }
                case CellType.Shift:
                    {
                        which = HasAnyNotes ? Theme.AnyNotes : Theme.Shift;                        
                        break;
                    }
                case CellType.JobPosition:
                    {
                        which = Theme.Shift;
                        isNativeElement = true;
                        break;
                    }
            }
            assigned.Add(Program.CurrentTheme.GetColour(which));
            #endregion

            if (!IsEditable && HasAnyNotes) // for IsEditable Cells (Shift / Blank) it has already been added in Step #1
            {
                assigned.Add(Program.CurrentTheme.GetColour(Theme.AnyNotes));
            }

            if (!isNativeElement)
            {
                if (GetParentMode == SheetType.Rota)
                {
                    var myStatus = GetMyStatus;
                    if (myStatus.IsShut())
                    {
                        assigned.Clear();
                        assigned.Add(Program.CurrentTheme.GetColour(Theme.Shut));
                    }
                    if (myStatus.IsInventory())
                    {
                        assigned.Add(Program.CurrentTheme.GetColour(Theme.Inventory));
                    }
                }

                /* If there is more than one colour to be applied,
                 * and the Cell is IsEditable (either Shift or Blank),
                 * then we take its basic colour out of the equation
                 * so that it doesn't unnecessarily "water down" the extra colours we need to apply. */
                if ((assigned.Count > 1) && (IsEditable))
                {
                    var firstone = assigned[0];
                    firstone.BackColour = null;
                    assigned[0] = firstone;
                }

                if (GetParent.Mode == SheetType.Rota)
                {
                    if (GetMyDate < DateTime.Now.Date)
                    {
                        assigned.AddAsManyAsCount(Program.CurrentTheme.GetColour(Theme.Past));
                    }
                    if (GetMyDate == DateTime.Now.Date)
                    {
                        assigned.AddAsManyAsCount(Program.CurrentTheme.GetColour(Theme.Today));
                    }
                }
            }
            #region those which are added "strongly" (that is - doubling the array)
            if (MyCellType == CellType.Shift)
            {
                var hours = GetParentWorkingHours;
                var m = Shift.WhatMismatch(Shifts.ToArray(), hours);
                if (m != Mismatch.None)
                {
                    assigned.AddAsManyAsCount(Program.CurrentTheme.GetColour(Theme.WorkingHrsMismatch));
                }
                if (Shifts.MarkedAsOdd)
                {
                    assigned.AddAsManyAsCount(Program.CurrentTheme.GetColour(Theme.TemplateMismatch));
                }
            }
            if (HasAnyRequests)
            {
                var requests = GetMyRequests;
                if (requests.CollideWith(Shifts.ToArray(), true))
                {
                    assigned.AddAsManyAsCount(Program.CurrentTheme.GetColour(Theme.RequestViolation));
                }
                else
                {
                    assigned.Add(Program.CurrentTheme.GetColour(Theme.Request));
                }
            }
            #endregion
            #region mixing (calculating) the finalStyle resulting colour, as well as boldness of the font and returning the Value
            var finalStyle = Theme.MixColours(assigned.ToArray());
            var bold = false;
            foreach (var c in assigned.Where(c => c.Bold.HasValue).Where(c => c.Bold.Value))
            {
                bold = true;
            }
            finalStyle.Bold = bold;

            style.Backcolor = finalStyle.BackColour.Value;
            style.Forecolor = finalStyle.ForeColour.Value;
            style.Bold = finalStyle.Bold.Value;

            return style;
            #endregion
        }
    }
}
